package com.hnkywl.sts.listener;

import com.hnkywl.sts.interceptor.AuthInterceptor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: Administrator
 * Date: 13-5-8
 * Time: 下午9:36
 * To change this template use File | Settings | File Templates.
 */
public class OnlineListener implements HttpSessionListener, HttpSessionAttributeListener, ServletRequestListener {
    private WebApplicationContext ctx;
    private OnlineInfo onlineInfo;

    //Session创建时
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        onlineInfo = (OnlineInfo) getBean("onlineInfo", se.getSession().getServletContext());
        onlineInfo.addSession(se.getSession().getId(), se.getSession());
    }

    //Session失效时
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        onlineInfo.remove(se.getSession().getId());
        onlineInfo.delSession(se.getSession().getId());
    }

    //Session添加内容时
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        //判断为用户登录动作
        if (isUserSession(se)) {
            onlineInfo.add(se.getSession().getId(), getUserInfo(se));
        }
    }

    //Session删除内容时
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        if (isUserSession(se)) {
            onlineInfo.remove(se.getSession().getId());
        }
    }

    //Session内容变化时
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        if (isUserSession(se)) {
            //删除列表中的用户，添加列表
            onlineInfo.remove(se.getSession().getId());
            onlineInfo.add(se.getSession().getId(), getUserInfo(se));
        }
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        if (onlineInfo != null)
            onlineInfo.log(request);
    }

    //request创建时
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        //取得客户的IP,放入Session中
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        setRemoteIP(request.getSession(), request);
        setMACAddress(request.getSession(), this.getRemoteIP(request.getSession()));
    }

    private UserInfo getUserInfo(HttpSessionEvent se) {
        return new UserInfo(getUserId(se), getUserName(se), getRemoteIP(se.getSession()), getMACAddress(se.getSession()),
                getUserDeptName(se));
    }

    private Map getUser(HttpSessionEvent se) {
        if (se.getSession().getAttribute(AuthInterceptor.USER_SESSION_KEY) == null)
            return null;
        return (Map) se.getSession().getAttribute(AuthInterceptor.USER_SESSION_KEY);
    }

    private boolean isUserSession(HttpSessionBindingEvent se) {
        return AuthInterceptor.USER_SESSION_KEY.equals(se.getName());
    }

    private Long getUserId(HttpSessionEvent se) {
        return (Long) getUser(se).get("id");
    }

    private String getUserName(HttpSessionEvent se) {
        return getUser(se).get("xm").toString();
    }


    private String getUserDeptName(HttpSessionEvent se) {
        return getUser(se).get("zggsjc") + "-" + getUser(se).get("jgqc");
    }

    public void setRemoteIP(HttpSession session, HttpServletRequest request) {
        if (session.getAttribute("remoteIP") == null)
            session.setAttribute("remoteIP", getRemorteIP(request));
    }

    public String getRemoteIP(HttpSession session) {
        return session.getAttribute("remoteIP").toString();
    }

    public void setMACAddress(HttpSession session, String ip) {
        if (session.getAttribute("macAddress") == null)
            session.setAttribute("macAddress", "");//getMACAddress(ip));
    }

    public String getMACAddress(HttpSession session) {
        return session.getAttribute("macAddress").toString();
    }

    //获取IP地址
    public String getRemorteIP(HttpServletRequest request) {
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }

    public String getMACAddress(String ip) {
        String line = "";
        String macAddress = "";
        final String MAC_ADDRESS_PREFIX = "MAC Address = ";
        final String MAC_ADDRESS_PREFIX_ZH = "MAC 地址 = ";
        final String LOOPBACK_ADDRESS = "127.0.0.1";
        final String LOOPBACK_ADDRESS_V6 = "0:0:0:0:0:0:0:1";
        //如果为127.0.0.1,则获取本地MAC地址。
        if (LOOPBACK_ADDRESS.equals(ip) || LOOPBACK_ADDRESS_V6.equals(ip)) {
            InetAddress inetAddress = null;
            try {
                inetAddress = InetAddress.getLocalHost();

                //貌似此方法需要JDK1.6。
                byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
                //下面代码是把mac地址拼装成String
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < mac.length; i++) {
                    if (i != 0) {
                        sb.append("-");
                    }
                    //mac[i] & 0xFF 是为了把byte转化为正整数
                    String s = Integer.toHexString(mac[i] & 0xFF);
                    sb.append(s.length() == 1 ? 0 + s : s);
                }
                //把字符串所有小写字母改为大写成为正规的mac地址并返回
                macAddress = sb.toString().trim().toUpperCase();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (SocketException e) {
                e.printStackTrace();
            }
            return macAddress;
        }
        //获取非本地IP的MAC地址
        try {
            Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
            InputStreamReader isr = new InputStreamReader(p.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            while ((line = br.readLine()) != null) {
                int index = line.indexOf(MAC_ADDRESS_PREFIX);
                if (index != -1) {
                    macAddress = line.substring(index + MAC_ADDRESS_PREFIX.length()).trim().toUpperCase();
                } else {
                    index = line.indexOf(MAC_ADDRESS_PREFIX_ZH);
                    if (index != -1) {
                        macAddress = line.substring(index + MAC_ADDRESS_PREFIX_ZH.length()).trim().toUpperCase();
                    }
                }
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace(System.out);
        }
        return macAddress;
    }


    private Object getBean(String name, ServletContext sc) {
        if (ctx == null) {
            ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
        }
        return ctx.getBean(name);
    }
}
